package com.carey.oauth.main;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.carey.gae.data.OAuthProperties;
import com.carey.gae.data.PropertiesManager;
import com.carey.openoauth.encoders.OAuthException;
import com.carey.openoauth.http.Request;
import com.carey.openoauth.http.Response;
import com.carey.openoauth.oauth.Scribe;
import com.carey.openoauth.oauth.Token;

/**
 * @author Carey R.S Zhou
 * 
 */
@SuppressWarnings("serial")
public class GAEOAuthServlet extends HttpServlet {
	private static final Logger log = Logger.getLogger(GAEOAuthServlet.class
			.getName());

	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		// resp.setContentType("text/plain");
		resp.setContentType("text/html; charset=UTF-8");
		// init out stream
		PrintWriter out = resp.getWriter();

		// get oauth_cmd
		String oauth_cmd = req.getParameter("oauth_cmd");
		log.info("oauth_cmd: " + oauth_cmd);

		// get consumer_key
		String consumer_key = req.getParameter("consumer_key");
		log.info("consumer_key: " + consumer_key);

		if (!isEmpty(oauth_cmd) && oauth_cmd.equalsIgnoreCase("RequestToken")) {
			// get RequestToken
			log.info("Get RequestToken");

			if (consumer_key == null) {
				return;
			}

			// init OAuthProperties
			OAuthProperties op = PropertiesManager.getProperty(consumer_key);
			if (op == null) {
				op = new OAuthProperties();
			}

			op.setConsumer_key(consumer_key);
			op.setConsumer_secret(req.getParameter("consumer_secret"));
			op.setHttp_method(req.getParameter("http_method"));
			op.setRequest_token_url(req.getParameter("request_token_url"));
			op.setAccess_token_url(req.getParameter("access_token_url"));
			op.setAuthorize_token_url(req.getParameter("authorize_token_url"));
			op.setOauth_signature_method(req
					.getParameter("oauth_signature_method"));

			// init Properties
			Properties tp = new Properties();
			tp.setProperty(Scribe.CONSUMER_KEY, op.getConsumer_key());
			tp.setProperty(Scribe.CONSUMER_SECRET, op.getConsumer_secret());
			tp.setProperty(Scribe.REQUEST_TOKEN_VERB, op.getHttp_method());
			tp.setProperty(Scribe.REQUEST_TOKEN_URL, op.getRequest_token_url());
			tp.setProperty(Scribe.ACCESS_TOKEN_VERB, op.getHttp_method());
			tp.setProperty(Scribe.ACCESS_TOKEN_URL, op.getAccess_token_url());
			tp.setProperty(Scribe.CALLBACK_URL, req.getRequestURL().toString());

			try {
				Scribe sb = new Scribe(tp);
				Token tk = sb.getRequestToken(out);

				// update request token
				op.setRequest_token(tk.getToken());
				op.setRequest_token_secret(tk.getSecret());

				// update authorize token
				op.setAuthorize_token(tk.getToken());

				// save Properties
				PropertiesManager.setProperty(consumer_key, op);

				out.print("<BeginAuthorize>");
				out.print(op.getAuthorize_token_url() + "?oauth_token="
						+ op.getAuthorize_token());
				out.print("<EndAuthorize>");
			} catch (OAuthException e) {
				log.warning("OAuthException: " + e.getMessage());
				out.println("OAuthException: " + e.getMessage());
			}
		} else if (!isEmpty(oauth_cmd)
				&& oauth_cmd.equalsIgnoreCase("AccessToken")) {
			// get AccessToken
			log.info("Get AccessToken");

			if (consumer_key == null) {
				return;
			}

			// init OAuthProperties
			OAuthProperties op = PropertiesManager.getProperty(consumer_key);
			if (op == null) {
				return;
			}

			// init Properties
			Properties tp = new Properties();
			tp.setProperty(Scribe.CONSUMER_KEY, op.getConsumer_key());
			tp.setProperty(Scribe.CONSUMER_SECRET, op.getConsumer_secret());
			tp.setProperty(Scribe.REQUEST_TOKEN_VERB, op.getHttp_method());
			tp.setProperty(Scribe.REQUEST_TOKEN_URL, op.getRequest_token_url());
			tp.setProperty(Scribe.ACCESS_TOKEN_VERB, op.getHttp_method());
			tp.setProperty(Scribe.ACCESS_TOKEN_URL, op.getAccess_token_url());
			tp.setProperty(Scribe.CALLBACK_URL, req.getRequestURL().toString());

			try {
				Scribe sb = new Scribe(tp);
				Token tk = new Token(op.getRequest_token(), op
						.getRequest_token_secret());
				tk = sb.getAccessToken(tk, op.getAuthorize_token_verifier(),
						out);

				// update access token
				op.setAccess_token(tk.getToken());
				op.setAccess_token_secret(tk.getSecret());

				// save Properties
				PropertiesManager.setProperty(consumer_key, op);

				out.print("<BeginAccessToken>");
				out.print(tk);
				out.print("<EndAccessToken>");
			} catch (OAuthException e) {
				log.warning("OAuthException: " + e.getMessage());
				out.println("OAuthException: " + e.getMessage());
			}
		} else if (!isEmpty(oauth_cmd) && oauth_cmd.equalsIgnoreCase("RunAPI")) {
			log.info("RunAPI");

			if (consumer_key == null) {
				return;
			}

			// init OAuthProperties
			OAuthProperties op = PropertiesManager.getProperty(consumer_key);
			if (op == null) {
				return;
			}

			// init Properties
			Properties tp = new Properties();
			tp.setProperty(Scribe.CONSUMER_KEY, op.getConsumer_key());
			tp.setProperty(Scribe.CONSUMER_SECRET, op.getConsumer_secret());
			tp.setProperty(Scribe.REQUEST_TOKEN_VERB, op.getHttp_method());
			tp.setProperty(Scribe.REQUEST_TOKEN_URL, op.getRequest_token_url());
			tp.setProperty(Scribe.ACCESS_TOKEN_VERB, op.getHttp_method());
			tp.setProperty(Scribe.ACCESS_TOKEN_URL, op.getAccess_token_url());
			tp.setProperty(Scribe.CALLBACK_URL, req.getRequestURL().toString());

			String api_url = req.getParameter("api_url");

			// RunAPI
			try {
				Scribe sb = new Scribe(tp);
				Request request = new Request(Request.Verb.GET, api_url);
				Token tk = new Token(op.getAccess_token(), op
						.getAccess_token_secret());
				sb.signRequest(request, tk);
				request.dumpRequest(out);

				Response response = request.send();
				String responseBody = response.getBody();
				log.info("responseBody: " + responseBody);
				response.dumpResponse(out);
			} catch (OAuthException e) {
				log.warning("OAuthException: " + e.getMessage());
				out.println("OAuthException: " + e.getMessage());
			}
		} else if (isEmpty(oauth_cmd)) { // Authorize callback
			log.info("Authorize callback");

			String oauth_callback_token = req.getParameter("oauth_token");
			String oauth_callback_verifier = req.getParameter("oauth_verifier");
			if (isEmpty(oauth_callback_token)
					|| isEmpty(oauth_callback_verifier)) {
				return;
			}

			// init OAuthProperties
			OAuthProperties op = PropertiesManager
					.getPropertyByAuthorizeToken(oauth_callback_token);
			if (op == null) {
				return;
			}
			op.setAuthorize_token_verifier(oauth_callback_verifier);
			
			// save Properties
			PropertiesManager.setProperty(op.getConsumer_key(), op);

			out.println("Authorize Success");
			out.println("oauth_token ==> " + oauth_callback_token);
			out.println("oauth_verifier ==> " + oauth_callback_verifier);
		}
	}

	boolean isEmpty(String str) {
		return (str == null) || (str.trim().length() == 0);
	}
}
